#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "restaurantdatamanager.h"
#include "searchhistorydialog.h"
#include "settingsdialog.h"


#include <QtGui>
#include <QJson/Parser>
#include <QJson/Serializer>
#include <QJson/QObjectHelper>


MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    m_authorName               = "Tu Nguyen";
    m_appName                  = "Find place v0.1";

    QSettings settings(m_authorName, m_appName);
    m_strApiKey = settings.value("apiKey").toString();
    //m_strApiKey                = "AIzaSyAyT5DOdbrsgTvQlBrk7ZfhXMxiiyAEu_0";
    m_maxNumberOfDisplayPlaces = 10;
    m_savedFilePath            = QDir::currentPath() + "/userdata";
    m_savedFileName            = "saved.json";

    m_pDataManager = new RestaurantDataManager(this);

    // Create model
    model = new QStringListModel(this);
    ui->placeDetailsListView->setModel(model);

    //Connect to setting diaglog
    connect(ui->actionSetting, SIGNAL(triggered()), this, SLOT(editSettings()));

    //Connect the history search diaglog
    connect(ui->actionOpen_search_history, SIGNAL(triggered()), this, SLOT(showSearchHistoryDialog()));

    //Connect QLineEdit to search button clicked
    connect(ui->lineSearchAddress, SIGNAL(returnPressed()), ui->pbSearchRestaurant, SIGNAL(clicked()));

    //connect RestaurantDataManager class to this form via errorOccured signal
    connect(m_pDataManager, SIGNAL(errorOccured(QString)), this, SLOT(errorOccured(QString)));

    //When a location is found, this object will search for place based on location found
    connect(m_pDataManager, SIGNAL(locationFound(QString)), this, SLOT(searchPlacesNearbyLocation(QString)));

    //When a list of place is found, this object will search detail information of each
    connect(m_pDataManager, SIGNAL(placeFound(QString)), this, SLOT(searchPlaceDetails(QString)));

    connect(m_pDataManager, SIGNAL(placeDetailsFound(Place)), this, SLOT(updatePlaceDetails(Place)));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pbSearchRestaurant_clicked()
{
    QString address = ui->lineSearchAddress->text();

    //clean the privous result
    model->setStringList(QStringList());
    m_pDataManager->searchLocationByAddress(m_strApiKey ,address);
    return;
}

void MainWindow::on_pbSavePlaceDetailsResult_clicked()
{
    QFile jsonFile(m_savedFilePath + "/" + m_savedFileName);

    QString location    = ui->lineSearchAddress->text();
    QStringList results = getPlaceDetail();
    if(!results.empty())
    {
       addSearchResult(jsonFile, new SearchResult(location, results));
    }
}

QVariant MainWindow::loadJsonFileRaw(QFile& jsonFile)
{
    if(!jsonFile.exists())
    {
        QDir directory(m_savedFilePath);
        directory.mkdir(m_savedFilePath);
    }

    if (!jsonFile.open(QFile::ReadWrite)) {
        errorOccured("Failed to open JSON file:" + jsonFile.fileName());
        return QString();
    }

    QVariant read_msg = jsonFile.readAll();
    jsonFile.close();
    return read_msg;
}

void MainWindow::clearJsonFileRaw(QFile &jsonFile)
{
    if(jsonFile.exists())
    {
        //Clearn the json file
        jsonFile.resize(0);
        jsonFile.close();
    }
}

/*
  Read the user saved data from json file
*/
QList<SearchResult*> MainWindow::getSearchResults(QFile &jsonFile)
{
    //Open the json file
    QByteArray rawFile = loadJsonFileRaw(jsonFile).toByteArray();
    //Parse the Json file into Qvariant
    QJson::Parser parser;
    bool ok;
    QVariant jsonDataParsed = parser.parse(rawFile, & ok);
    //Build the list of search result
    QList<SearchResult*> search_result;

    if(ok)
    {
        foreach(QVariant json_search_result, jsonDataParsed.toList())
        {
            QString        location = json_search_result.toMap()["location"].toString();

            //Copy the list of variant to list of string
            QStringList    results;
            foreach(QVariant result, json_search_result.toMap()["results"].toList())
            {
                results << result.toString();
            }
            search_result.append(new SearchResult(location, results));
        }
    }
    else
    {
        clearJsonFileRaw(jsonFile);
    }

    return search_result;
}

void MainWindow::addSearchResult(QFile &jsonFile, SearchResult* adding_result)
{
    QList<SearchResult*> current_results = getSearchResults(jsonFile);
    current_results.append(adding_result);

    clearJsonFileRaw(jsonFile);
    jsonFile.open(QFile::WriteOnly);
    jsonFile.write("[");
    foreach(SearchResult* item, current_results)
    {
      QVariantMap variant = QJson::QObjectHelper::qobject2qvariant(item);
      QJson::Serializer serializer;
      jsonFile.write( serializer.serialize(variant));
      if(current_results.last() != item)
      {
         jsonFile.write(",");
      }
    }
    jsonFile.write("]");

    //release resource
    clearSearchResult(current_results);
}

void MainWindow::clearSearchResult(QList<SearchResult *> searchResults)
{
    foreach(SearchResult* item, searchResults)
    {
        if(item)
        {
           delete item;
        }
    }

    searchResults.clear();
}

void MainWindow::searchPlacesNearbyLocation(const QString &location)
{
    m_pDataManager->searchRestaurantByLocation(m_strApiKey, "vi", "restaurant", location);
    return;
}

void MainWindow::searchPlaceDetails(const QString & place_id)
{
    m_pDataManager->searchRestaurantDetails(m_strApiKey, place_id, "vi");
    return;
}

void MainWindow::updatePlaceDetails(const Place & place_detail)
{
    if((uint)model->rowCount() < m_maxNumberOfDisplayPlaces)
    {
        QString s_place_detail;
        s_place_detail = "Name: "                 + place_detail.getName() + "\n" +
                         "Address: "              + place_detail.getAddress() + "\n" +
                         "Phone Number: "         + place_detail.getPhoneNumber();
        model->insertRow(model->rowCount());
        QModelIndex index = model->index(model->rowCount()-1);
        model->setData(index, s_place_detail);
    }
    return;
}

void MainWindow::showSearchHistoryDialog()
{
    SearchHistoryDialog searchHistory;

    QFile jsonFile(m_savedFilePath + "/" + m_savedFileName);
    QList<SearchResult*> search_result = getSearchResults(jsonFile);

    searchHistory.loadData(search_result);
    searchHistory.exec();

}

void MainWindow::
errorOccured(const QString & error)
{
    QMessageBox::warning(this, trUtf8("Error"), error);
}

QStringList MainWindow::getPlaceDetail() const
{
  return model->stringList();
}

void MainWindow::
editSettings()
{
    SettingsDialog dialog(m_authorName, m_appName, this);
    dialog.exec();

}
